[iOS] NSString
1 はじめに
NSStringは、文字列を扱う標準のクラスです。
NSString内の文字列は、一旦、作成されるとその内容を変更することはできません。 生成後に、その内容を変更したい場合は、NSMutableStringクラスを使います。
文字列オブジェクトは、内部的には、Unicode文字列の配列として表現されており、lengthメソッドで文字数、characterAtIndex:メソッドで、特定の文字を取得することができます。 そして、この2つの「プリミティブ」メソッドが、文字列オブジェクト操作の基本となっています。
以下、いろいろな場面に向けて用意されているプロパティやメソッドを列挙してみます。
2 操作
(1) @記法
C言語の文字列のように、" "で包み、先頭に@をつけることで、NSStringオブジェクトを生成する記法が用意されています。 そして、これが、最も簡単なNSStringオブジェクトの生成方法だと思います。
NSString *name = @"Taro Yamamoto";
(2) C文字列との相互変化
文字コードがUTF−8で、最後に¥0となている、C言語タイプの文字列との相互変換は、次のようになります。
// C言語文字列からNSStringを生成 // - (instancetype)initWithUTF8String:(const char *)bytes NSString *name = [[NSString alloc] initWithUTF8String:"Taro Yamamoto"]; // NSStirngからC言語を生成 // @property(readonly) const char *UTF8String const char *p = [name UTF8String];
(3) 長さ(文字数)
オブジェクトに含まれる文字数を取得するには、lengthプロパティが利用されます。(バイト数や表示幅には利用できません)
// 長さを取得する // @property(readonly) NSUInteger length NSString *name = @"Taro Yamamoto"; int len = [name length]; // len = 13
(4) 文字の取得
指定した位置の文字を取得する。なお、取得した文字は、charでは無く、unichar型です。
// 指定位置の文字取得 // - (unichar)characterAtIndex:(NSUInteger)index NSString *name = @"Taro Yamamoto"; //インデックス2の文字を取得する unichar c = [name characterAtIndex:2]; // 'r'
3 文字列コードの変換
NSStringとは、文字列やバイト列と相互にエンコード・デコードが可能です。 そして、この際の文字コードの種類の指定には、NSStringEncoding型が定義されており、主なものに次のようなものがあります。
NSASCIIStringEncoding // 7bit ASCIIエンコーディング NSMacOSRomanStringEncoding // Classic Macintosh Romanエンコーディング NSUTF8StringEncoding // UTF-8エンコーディング NSJapaneseEUCStringEncoding // 日本語8bit EUCエンコーディング NSShiftJISStringEncoding // 日本語8bit Shift-JISエンコーディング
(1) NSString <- C文字列
指定した文字コードで、最後が¥0となっている、C言語タイプの文字列からの生成です。
// 文字コードを指定したC文字列からの生成 // - (instancetype)initWithCString:(const char *)nullTerminatedCString // encoding:(NSStringEncoding)encoding NSString *str0 = [[NSString alloc] initWithCString:"あいうえお" encoding:NSUTF8StringEncoding]; // 文字コードを指定したC文字列からの生成(コンビニエンスコンストラク) // + (instancetype)stringWithCString:(const char *)cString // encoding:(NSStringEncoding)enc NSString *str1 = [NSString stringWithCString:"かきくけこ" encoding:NSUTF8StringEncoding];
(2) NSString -> C文字列
続いて、指定した文字コードで、C言語タイプの文字列を生成です。 指定した文字コードに変換できなかった場合は、例外となります。
// C文字列の生成 // - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding NSString *str = @"さしすせそ"; printf("%s\n", [str cStringUsingEncoding:NSUTF8StringEncoding]);
(3) NSStirng <- バイト列
バイト列(NSData)からの生成です。
// NSDataからの生成 // - (instancetype)initWithData:(NSData *)data // encoding:(NSStringEncoding)encoding const char* s = "12345"; NSData *data = [NSData dataWithBytes:s length:5 ]; NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; // バイト列からの生成(バイト数指定) // - (instancetype)initWithBytes:(const void *)bytes // length:(NSUInteger)length // encoding:(NSStringEncoding)encoding const char* data = "12345"; NSString *str = [[NSString alloc] initWithBytes:data length:5 encoding:NSUTF8StringEncoding];
(4) NSString -> バイト列
指定した文字コードでエンコードされたNSDataを生成します。 変換できない場合、nilとなります。
// NSDataの生成 // - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding NSString *str = @"たちつてと"; NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; // エンコード後のバイト数の取得 // - (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)enc NSUInteger *len = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
(5) エンコードの可否判定
指定した文字コードへの変換が可能かどうかを判定します。
// エンコードの可否判定 // - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding NSString *str = @"abcde"; BOOL isAscii = [str canBeConvertedToEncoding:NSASCIIStringEncoding];
(6) パーセント符号化
指定した文字コードにしたがって、URL文字列表現で使用するパーセント符号化します。
// パーセント符号化 // - (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding NSString* inputString = @"http://www.exsample.com/index.php?data=テスト"; NSString* encodeString = [inputString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //@"http://www.exsample.com/index.php?data=%E3%83%86%E3%82%B9%E3%83%88" // パーセント符号化から戻す // - (NSString *)stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding NSString *outputString = [encodeString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
4 書式指定による文字列作成
NSStringでは、書式文字列を使用した文字列の生成が可能です。 なお、書式文字列自体もNSStringです。
// 書式文字列によるNSStringの生成 // - (instancetype)initWithFormat:(NSString *)format NSInteger n = 100000000; NSString *str0 = [[NSString alloc]initWithFormat:@"文字列:%ld", n]; // 書式文字列によるNSStringの生成(コンビニエンスコンストラクタ) // + (instancetype)stringWithFormat:(NSString *)format NSString *str1 = [NSString stringWithFormat:@"文字列; %ld",n];
C言語と違って、%@ と言う書式指定子がありますが、これは、引数にオブジェクト(NSObject)を取り、そのオブジェクトにdescriptionというメッセージを送って、受け取っとNSStringが、そこに挿入されます。
5 比較
比較の結果として返されるNSComparisonResultは、次の3つの値をとる列挙型です。
NSComparisonResult result = [ str1 compare : str2]; switch (result) { case NSOrderedAscending: NSLog(@"小さい (-1)"); break; case NSOrderedSame: NSLog(@"等しい (0)"); break; case NSOrderedDescending: NSLog(@"大きい (1)"); break; }
(1) 文字列の比較
// 文字列の比較 // - (NSComparisonResult)compare:(NSString *)aString NSString* str1 = @"abc"; NSString* str2 = @"efd"; NSComparisonResult result = [ str1 compare : str2]; // result = NSOrderedAscending(小さい)
(2) 英文字の大文字・小文字を区別しないで比較
// 英数大文字・小文字を区別しない比較 // - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString NSString* str1 = @"abc"; NSString* str2 = @"ABC"; NSComparisonResult result = [str1 caseInsensitiveCompare:str2]; // result = NSOrderedSame(等しい)
(3) 等しいかどうか
// 文字列が等しいかどうかの判定 // - (BOOL)isEqualToString:(NSString *)aString NSString* str1 = @"abc"; NSString* str2 = @"ABC"; BOOL resutl = [str1 isEqualToString:str2]; // result = NO
(4) 先頭・末尾と一致するかどうか
// 先頭一致判定 // - (BOOL)hasPrefix:(NSString *)aString // 末尾一致判定 // - (BOOL)hasSuffix:(NSString *)aString NSString* str = @"abcdefg"; BOOL result0 = [str hasPrefix:@"abc"]; // 文字列が"abc"から始まる場合TRUE BOOL result1 = [str hasSuffix:@"efg"]; // 文字列が"efg"で終わる場合TRUE // 先頭から比較して一致した部分を返す // - (NSString *)commonPrefixWithString:(NSString *)aString // options:(NSStringCompareOptions)mask NSString *result2 = [str commonPrefixWithString:@"abc" options:NSLiteralSearch]; // result2 = "abc"
最後のcommonPrefixWithStringで使用されたNSStringCompareOptionsには、以下のような指定が可能です。
- NSCaseInsensitiveSearch 1 大文字と小文字を区別しない
- NSLiteralSearch 2 完全一致
- NSBackwardsSearch 4 文末から検索
- NSAnchoredSearch 8 検索で最初にヒットした文字を拾う(NSBackwardsSearchでは最後)
commonPrefixWithStringでは、文字列の途中からの比較はできません。
6 結合
結合は、対象オブジェクトの後ろに追加する形で利用されます。
// 後ろに文字列を追加して、新しい文字列を生成する // - (NSString *)stringByAppendingString:(NSString *)aString NSString* str1 = @"abc"; NSString* str2 = @"ABC"; NSString *str3 = [str1 stringByAppendingString:str2]; // str3 = @"abcABC" // 後ろに書式文字列を追加して、新しい文字列を生成する // - (NSString *)stringByAppendingFormat:(NSString *)format // , ... int n = 100; NSString *str4 = [str1 stringByAppendingFormat:@"%ld",n]; // str4 = @"abc100"
7 部分文字列
指定した部分の文字列を切り出すことができます。
// 先頭から指定したインデックスまでの文字列を切りだす // - (NSString *)substringToIndex:(NSUInteger)anIndex NSString *str0 = [@"あいうえお" substringToIndex:3]; // str0 = @"あいう" // 指定したインデックスから最後までの文字列を切りだす // - (NSString *)substringFromIndex:(NSUInteger)anIndex NSString *str1 = [@"あいうえお" substringFromIndex:3]; // str1 = @"えお" // 指定した範囲の文字列を切りだす // - (NSString *)substringWithRange:(NSRange)aRange NSString *str3 = [@"あいうえお" substringWithRange:NSMakeRange(1,3)]; //str3 = @"いうえ"
8 分割
セパレータ文字列を指定して、文字列を分割します。
// 指定した文字列で分割する // - (NSArray<NSString *> *)componentsSeparatedByString:(NSString *)separator NSString *str = @"abc:def:ghi"; NSArray *arr = [str componentsSeparatedByString:@":"]; // arr[0] = @"abc" // arr[1] = @"def" // arr[2] = @"ghi"
複数の文字をセパレータに指定することもできます。
// セパレータ文字を指定して分割する // - (NSArray<NSString *> *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator NSString *str = @"https://dev.classmethod.jp/"; NSCharacterSet *spr = [NSCharacterSet characterSetWithCharactersInString:@".:/"]; NSArray *arry = [str componentsSeparatedByCharactersInSet:spr]; // arry[0] = "http" // array[1] = "" // array[2] = "" // array[3] = "dev" // array[4] = "classmethod" // array[5] = "jp" // array[6] = ""
セパレータとして指定する文字セットは、予め用意されているものを使用することもできます。
9 検索
文字列の中から、パターンを検出することができます。 そして、多数の問題解決が、この検索の機能を応用することで実現可能になります。
(1) パターン検出
// 文字列の中で、どこに同じパターンがあるかを検索する // - (NSRange)rangeOfString:(NSString *)aString // 文字列の中に@"BBB"というパターンが存在するかどうか NSRange searchResult = [@"AAABBBCCC" rangeOfString: @"BBB"]; if(searchResult.location == NSNotFound){ // 見つからない }else{ // searchResult = location=3, length=3 // 3文字目から3文字の場所に見つかった }
(2) 条件付パターン検出
rangeOfStringによる検索は、オプション指定して、使用することもできます。
// 文字列の中で、どこに同じパターンがあるかを検索する(オプション指定あり) // - (NSRange)rangeOfString:(NSString *)aString // options:(NSStringCompareOptions)mask // 大文字小文字を区別せずに検索する NSRange searchResult = [@"AAABBBCCC" rangeOfString:@"bbb" options:NSCaseInsensitiveSearch]; if(searchResult.location == NSNotFound){ // 見つからない }else{ // searchResult = location=3, length=3 // 3文字目から3文字の場所に見つかった }
(3) 行分割
指定した範囲を含んだ行を返すメソッドがあります。 これを利用すると、複数の行を1行づつ順番に取得することができます。
// 指定した範囲を含む行の範囲を返す // - (NSRange)lineRangeForRange:(NSRange)aRange // 1行ずつ読み出す NSString *lines = @"AAA\nBBB\nCCC\nDDD\n"; NSUInteger lineEnd = 0; while (lineEnd < [lines length]) { NSRange currentRange = [lines lineRangeForRange:NSMakeRange(lineEnd, 0)]; NSString *currentLine = [lines substringWithRange:currentRange]; lineEnd = currentRange.location + currentRange.length; }
(4) 正規表現
検索では、オプションにNSRegularExpressionSearchを指定して、正規表現を使用することもできます。 次の例は、正規表現を使用して、3桁の数値が含まれているかどうかを確認しています。
//3つの連続した数値を表現する正規表現 NSString* expression = @"[0-9]{3}"; NSRange range = [@"aaabbbccc628ddd" rangeOfString:expression options:NSRegularExpressionSearch]; if (range.location != NSNotFound) { NSLog(@"3桁の数値が含まれている"); }
10 置換
// 指定した範囲を指定した文字列で置き換える // - (NSString *)stringByReplacingCharactersInRange:(NSRange)range // withString:(NSString *)replacement // 3文字目から5文字を"x"で置き換える NSString *str = [@"123456789" stringByReplacingCharactersInRange:NSMakeRange(3,5) withString:@"x"]; // str = @"123x9"
// 指定したパターンを指定した文字列で置き換える // - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target // "," を全て "-" に置き換える NSString *hoge = @"0,1,2,3,4"; NSString *str = [hoge stringByReplacingOccurrencesOfString: @"," withString: @"-"]; // str = @"0-1-2-3-4"
11 大文字・小文字化
英文字を全て、大文字にしたり、小文字にしたりします。
NSString *str0 = @"AbCDEfg"; // 英文字を全て小文字にする // @property(readonly, copy) NSString *lowercaseString NSString *str1 = [str0 lowercaseString]; // str1 = "abcdefg" // 英文字を全て大文字にする // @property(readonly, copy) NSString *uppercaseString NSString *str2 = [str0 uppercaseString]; // str1 = "ABCDEFG"
12 型へのキャスト
それそれの型へ変換します。 評価の際に文字列の先頭に含まれる空白は無視されます。
なお、boolValueに関しては、先頭文字がY,y,T,tのいづれか、または、、先頭に0以外の10進数がある場合に、YESを返します。
int i = [@"123" intValue]; double d = [@"0.1" doubleValue]; float f = [@"0.1" floatValue]; NSInteger n = [@"123" integerValue]; bool b = [@"true" boolValue];
13 ファイルパスからファイル名や拡張子への変換
フルパスから必要な文字列を取得する要領は、次の通りです。
NSString *path = [NSString stringWithFormat:@"user/local/sample.txt"]; NAString *fileName = [path lastPathComponent]; // sample.txt NSString *directory = [path stringByDeletingLastPathComponent]; // user/local NSString *extension = [fileName pathExtension]; // txt
14 最後に
NSStringは、非常に高機能で、多くのプロパティやメソッドがあります。 全てを列挙するのは難しいのですが、とりあえず、困らない程度に、使えるものを列挙できたかと思います。